package com.beiding.hotcode;

import java.io.File;
import java.io.IOException;
import java.util.*;

//Java类持有者
class ClassFileHolder {

    //父文件夹
    private File parentFile;

    //内部类前缀
    private String innerClassFilePrefix;

    //文件和文件数据的Map
    private Map<String, FileDetails> aboutDataMap = new HashMap<>();

    private FileDetails mainClassFileDetails;

    private MyOrderedClassLoader reloadClassLoader;

    private Class clazz;

    void reloadClassLoader(MyOrderedClassLoader reloadClassLoader) {
        this.reloadClassLoader = reloadClassLoader;
    }

    Class checkReloadAndGet() {
        if (reloadClassLoader != null) {
            try {
                scan();
                clazz = this.reloadClassLoader.define(this);
                System.out.println("重载类:"+clazz.getName());
                reloadClassLoader = null;
            } catch (Exception e) {
                System.out.println("类加载问题");
            }
        }
        return clazz;
    }

    ClassFileHolder(File classFile) {
        mainClassFileDetails = new FileDetails();
        mainClassFileDetails.file = classFile;
        parentFile = classFile.getParentFile();
        String name = classFile.getName();
        name = name.substring(0, name.lastIndexOf(".class"));
        innerClassFilePrefix = name + "$";
    }

    //首先进行一次扫描操作
    void scan() throws Exception {
        File[] files = parentFile.listFiles();
        Set<String> retainFiles = new HashSet<>();
        if (files != null) {
            for (File file : files) {
                if (file.isFile()) {
                    String fileName = file.getName();
                    FileDetails fileDetails = aboutDataMap.get(fileName);
                    if (fileDetails == null) {
                        if (fileName.startsWith(innerClassFilePrefix) && fileName.endsWith(".class")) {
                            fileDetails = new FileDetails();
                            fileDetails.file = file;
                            fileDetails.checkReload();
                            aboutDataMap.put(fileName, fileDetails);
                            retainFiles.add(fileName);
                        }
                    } else {
                        //检查是否需要重新载入数据
                        fileDetails.checkReload();
                        retainFiles.add(fileName);
                    }
                }
            }
        }

        //移除不需要保留的文件
        if (retainFiles.size() != aboutDataMap.size()) {
            Set<String> all = new HashSet<>(aboutDataMap.keySet());
            all.removeAll(retainFiles);
            for (String s : all) {
                aboutDataMap.remove(s);
            }
        }

        mainClassFileDetails.checkReload();

    }

    byte[] getMainData() {
        return mainClassFileDetails.data;
    }

    List<byte[]> getAboutClassData() {
        List<byte[]> all = new ArrayList<>();
        for (FileDetails details : aboutDataMap.values()) {
            all.add(details.data);
        }
        return all;
    }

    //TODO 检查文件变化??
    private static class FileDetails {
        byte[] data;
        //上次加载时间
        long lastLoadTime = 0;
        File file;

        void checkReload() throws IOException {
            long lastChangeTime = file.lastModified();
            if (lastChangeTime != lastLoadTime) {
                data = FileUtils.readFileData(file);
                lastLoadTime = lastChangeTime;
            }
        }
    }

}
